home *** CD-ROM | disk | FTP | other *** search
/ Personal Computer World 2008 February / PCWFEB08.iso / Software / Resources / Developers / XAMPP 1.5.4 / Windows installer / xampp-win32-1.5.4-installer.exe / xampp / php / pear / SOAP / Disco.php < prev    next >
Encoding:
PHP Script  |  2006-04-07  |  15.1 KB  |  385 lines

  1. <?php
  2. /**
  3.  * This file contains the code for the DISCO server, providing DISO and WSDL
  4.  * services.
  5.  *
  6.  * PHP versions 4 and 5
  7.  *
  8.  * LICENSE: This source file is subject to version 2.02 of the PHP license,
  9.  * that is bundled with this package in the file LICENSE, and is available at
  10.  * through the world-wide-web at http://www.php.net/license/2_02.txt.  If you
  11.  * did not receive a copy of the PHP license and are unable to obtain it
  12.  * through the world-wide-web, please send a note to license@php.net so we can
  13.  * mail you a copy immediately.
  14.  *
  15.  * @category   Web Services
  16.  * @package    SOAP
  17.  * @author     Dmitri Vinogradov <dimitri@vinogradov.de>
  18.  * @author     Chuck Hagenbuch <chuck@horde.org>
  19.  * @author     Jan Schneider <jan@horde.org>
  20.  * @copyright  2003-2005 The PHP Group
  21.  * @license    http://www.php.net/license/2_02.txt  PHP License 2.02
  22.  * @link       http://pear.php.net/package/SOAP
  23.  */
  24.  
  25. require_once 'SOAP/Base.php';
  26.  
  27. class SOAP_DISCO_Server extends SOAP_Base_Object {
  28.  
  29.     var $namespaces     = array(SCHEMA_WSDL => 'wsdl', SCHEMA_SOAP => 'soap');
  30.     var $import_ns      = array();
  31.     var $wsdl           = '';
  32.     var $disco          = '';
  33.     var $_wsdl          = array();
  34.     var $_disco         = array();
  35.     var $_service_name  = '';
  36.     var $_service_ns    = '';
  37.     var $_service_desc  = '';
  38.     var $_portname      = '';
  39.     var $_bindingname   = '';
  40.     var $soap_server    = NULL;
  41.  
  42.  
  43.     function SOAP_DISCO_Server($soap_server, $service_name, $service_desc = '',
  44.                                $import_ns = null)
  45.     {
  46.         parent::SOAP_Base_Object('Server');
  47.  
  48.         if ( !is_object($soap_server)
  49.             || !get_class($soap_server) == 'soap_server') return;
  50.  
  51.         $this->_service_name = $service_name;
  52.         $this->_service_ns = "urn:$service_name";
  53.         $this->_service_desc = $service_desc;
  54.         $this->import_ns = isset($import_ns) ? $import_ns : $this->import_ns;
  55.         $this->soap_server = $soap_server;
  56.         $this->host = isset($_SERVER['HTTP_HOST']) ? $_SERVER['HTTP_HOST'] : 'localhost';
  57.     }
  58.  
  59.     function getDISCO()
  60.     {
  61.         $this->_generate_DISCO();
  62.         return $this->disco;
  63.     }
  64.  
  65.     function getWSDL()
  66.     {
  67.         $this->_generate_WSDL();
  68.         return $this->wsdl;
  69.     }
  70.  
  71.     function _generate_DISCO()
  72.     {
  73.         // DISCO
  74.         $this->_disco['disco:discovery']['attr']['xmlns:disco'] = SCHEMA_DISCO;
  75.         $this->_disco['disco:discovery']['attr']['xmlns:scl'] = SCHEMA_DISCO_SCL;
  76.         $this->_disco['disco:discovery']['scl:contractRef']['attr']['ref'] =
  77.             (array_key_exists('HTTPS', $_SERVER) && $_SERVER['HTTPS'] == 'on')
  78.             ? 'https://' . $this->host . $_SERVER['PHP_SELF'] . '?wsdl'
  79.             : 'http://'  . $this->host . $_SERVER['PHP_SELF'] . '?wsdl';
  80.  
  81.         // generate disco xml
  82.         $this->_generate_DISCO_XML($this->_disco);
  83.     }
  84.  
  85.     function _generate_WSDL()
  86.     {
  87.         // WSDL
  88.         if (is_array($this->soap_server->_namespaces)) {
  89.             // need to get: typens, xsd & SOAP-ENC
  90.             $flipped = array_flip($this->soap_server->_namespaces);
  91.             $this->namespaces[$this->_service_ns] = 'tns';
  92.             $this->namespaces[$flipped['xsd']] = 'xsd';
  93.             $this->namespaces[$flipped['SOAP-ENC']] = 'SOAP-ENC';
  94.         }
  95.  
  96.         // DEFINITIONS
  97.         $this->_wsdl['definitions']['attr']['name'] = $this->_service_name;
  98.         $this->_wsdl['definitions']['attr']['targetNamespace'] = $this->_service_ns;
  99.         foreach ($this->namespaces as $ns => $prefix) {
  100.             $this->_wsdl['definitions']['attr']['xmlns:' . $prefix] = $ns;
  101.         }
  102.         $this->_wsdl['definitions']['attr']['xmlns'] = SCHEMA_WSDL;
  103.  
  104.         // Import namespaces. Seems to not work yet: wsdl.exe fom .NET can't
  105.         // handle imported complete wsdl-definitions.
  106.         if (count($this->import_ns)) {
  107.             $i = 0;
  108.             foreach ($this->import_ns as $_ns => $_location) {
  109.                 $this->_wsdl['definitions']['import'][$i]['attr']['location'] = $_location;
  110.                 $this->_wsdl['definitions']['import'][$i]['attr']['namespace'] = $_ns;
  111.                 $i++;
  112.             }
  113.         }
  114.         $this->_wsdl['definitions']['types']['attr']['xmlns']='http://schemas.xmlsoap.org/wsdl/';
  115.         $this->_wsdl['definitions']['types']['schema']=array();
  116.  
  117.         // Placeholder for messages
  118.         $this->_wsdl['definitions']['message'] = array();
  119.  
  120.         // PORTTYPE-NAME
  121.         $this->_portname = $this->_service_name . 'Port';
  122.         $this->_wsdl['definitions']['portType']['attr']['name'] = $this->_portname;
  123.  
  124.         // BINDING-NAME
  125.         $this->_bindingname = $this->_service_name . 'Binding';
  126.         $this->_wsdl['definitions']['binding']['attr']['name'] = $this->_bindingname;
  127.         $this->_wsdl['definitions']['binding']['attr']['type'] = 'tns:' . $this->_portname;
  128.         $this->_wsdl['definitions']['binding']['soap:binding']['attr']['style'] = 'rpc';
  129.         $this->_wsdl['definitions']['binding']['soap:binding']['attr']['transport'] = SCHEMA_SOAP_HTTP;
  130.  
  131.         // SERVICE
  132.         $this->_wsdl['definitions']['service']['attr']['name'] = $this->_service_name . 'Service';
  133.         $this->_wsdl['definitions']['service']['documentation']['attr'] = '';
  134.         $this->_wsdl['definitions']['service']['documentation'] = htmlentities($this->_service_desc);
  135.         $this->_wsdl['definitions']['service']['port']['attr']['name'] = $this->_portname;
  136.         $this->_wsdl['definitions']['service']['port']['attr']['binding'] = 'tns:' . $this->_bindingname;
  137.         $this->_wsdl['definitions']['service']['port']['soap:address']['attr']['location'] =
  138.             (array_key_exists('HTTPS', $_SERVER) && $_SERVER['HTTPS'] == 'on')
  139.             ? 'https://' . $this->host . $_SERVER['PHP_SELF']
  140.             : 'http://'  . $this->host . $_SERVER['PHP_SELF'];
  141.  
  142.         //
  143.         $dispatch_keys = array_keys($this->soap_server->dispatch_objects);
  144.         $dc = count($dispatch_keys);
  145.         for ($di = 0; $di < $dc; $di++) {
  146.             $namespace = $dispatch_keys[$di];
  147.             $namespace_objects =& $this->soap_server->dispatch_objects[$namespace];
  148.             $oc = count($namespace_objects);
  149.             for ($oi = 0; $oi < $oc; $oi++) {
  150.                 $object = $namespace_objects[$oi];
  151.                 // types definitions
  152.                 $this->addSchemaFromMap($object->__typedef);
  153.                 // MESSAGES
  154.                 $this->addMethodsFromMap($object->__dispatch_map, $namespace, get_class($object));
  155.             }
  156.         }
  157.         if (isset($server->dispatch_map)) {
  158.             $this->addMethodsFromMap($server->dispatch_map, $namespace);
  159.         }
  160.  
  161.         // generate wsdl
  162.         $this->_generate_WSDL_XML();
  163.     }
  164.  
  165.     function &_getSchema($namespace)
  166.     {
  167.         // SCHEMA
  168.         $c = count($this->_wsdl['definitions']['types']['schema']);
  169.         for($i = 0; $i < $c; $i++) {
  170.             if ($this->_wsdl['definitions']['types']['schema'][$i]['attr']['targetNamespace'] == $namespace) {
  171.                 return $this->_wsdl['definitions']['types']['schema'][$i];
  172.             }
  173.         }
  174.  
  175.         // don't have this namespace
  176.         $schema = array();
  177.         $schema['attr'] = array();
  178.         $schema['complexType'] = array();
  179.         $schema['attr']['xmlns'] = array_search('xsd',$this->namespaces);
  180.         $schema['attr']['targetNamespace'] = $namespace;
  181.         $this->_wsdl['definitions']['types']['schema'][] =& $schema;
  182.  
  183.         return $schema;
  184.     }
  185.  
  186.     function addSchemaFromMap(&$map)
  187.     {
  188.         if (!$map) {
  189.             return;
  190.         }
  191.  
  192.         foreach ($map as $_type_name => $_type_def) {
  193.             list($typens,$type) = $this->_getTypeNs($_type_name);
  194.             if ($typens == 'xsd') {
  195.                 // cannot add to xsd, lets use method_namespace
  196.                 $typens = 'tns';
  197.             }
  198.             $schema =& $this->_getSchema(array_search($typens, $this->namespaces));
  199.             if (!$this->_ifComplexTypeExists($schema['complexType'], $type)) {
  200.                 $ctype =& $schema['complexType'][];
  201.                 $ctype['attr']['name'] = $type;
  202.                 foreach ($_type_def as $_varname => $_vartype) {
  203.                     if (!is_int($_varname)) {
  204.                         list($_vartypens,$_vartype) = $this->_getTypeNs($_vartype);
  205.                         $ctype['all']['attr'] = '';
  206.                         $el =& $ctype['all']['element'][];
  207.                         $el['attr']['name'] = $_varname;
  208.                         $el['attr']['type'] = $_vartypens . ':' . $_vartype;
  209.                     } else {
  210.                         $ctype['complexContent']['attr'] = '';
  211.                         $ctype['complexContent']['restriction']['attr']['base'] = 'SOAP-ENC:Array';
  212.                         foreach ($_vartype as $array_var => $array_type) {
  213.                             list($_vartypens, $_vartype) = $this->_getTypeNs($array_type);
  214.                             $ctype['complexContent']['restriction']['attribute']['attr']['ref'] = 'SOAP-ENC:arrayType';
  215.                             $ctype['complexContent']['restriction']['attribute']['attr']['wsdl:arrayType'] = $_vartypens . ':' . $_vartype . '[]';
  216.                         }
  217.                     }
  218.                 }
  219.             }
  220.         }
  221.     }
  222.  
  223.     function addMethodsFromMap(&$map, $namespace, $classname = null)
  224.     {
  225.         if (!$map) {
  226.             return;
  227.         }
  228.  
  229.         foreach ($map as $method_name => $method_types) {
  230.             if (array_key_exists('namespace', $method_types)) {
  231.                 $method_namespace = $method_types['namespace'];
  232.             } else {
  233.                 $method_namespace = $namespace;
  234.             }
  235.             // INPUT
  236.             if (isset($method_types['in']) && is_array($method_types['in'])) {
  237.                 $input_message =& $this->_wsdl['definitions']['message'][];
  238.                 $input_message['attr']['name'] = $method_name . 'Request';
  239.                 foreach ($method_types['in'] as $name => $type) {
  240.                     list($typens, $type) = $this->_getTypeNs($type);
  241.                     $part =& $input_message['part'][];
  242.                     $part['attr']['name'] = $name;
  243.                     $part['attr']['type'] = $typens . ':' . $type;
  244.                 }
  245.             }
  246.  
  247.             // OUTPUT
  248.             if (isset($method_types['out']) && is_array($method_types['out'])) {
  249.                 $output_message =& $this->_wsdl['definitions']['message'][];
  250.                 $output_message['attr']['name'] = $method_name . 'Response';
  251.                 foreach ($method_types['out'] as $name => $type) {
  252.                     list($typens, $type) = $this->_getTypeNs($type);
  253.                     $part =& $output_message['part'][];
  254.                     $part['attr']['name'] = $name;
  255.                     $part['attr']['type'] = $typens . ':' . $type;
  256.                 }
  257.             }
  258.  
  259.             // PORTTYPES
  260.             $operation =& $this->_wsdl['definitions']['portType']['operation'][];
  261.             $operation['attr']['name'] = $method_name;
  262.  
  263.             // INPUT
  264.             $operation['input']['attr']['message'] = 'tns:'
  265.                             . $input_message['attr']['name'];
  266.  
  267.             // OUTPUT
  268.             $operation['output']['attr']['message'] = 'tns:'
  269.                             . $output_message['attr']['name'];
  270.  
  271.             // BINDING
  272.             $binding =& $this->_wsdl['definitions']['binding']['operation'][];
  273.             $binding['attr']['name'] = $method_name;
  274.             $action = $method_namespace . '#' . ($classname ? $classname . '#' : '') . $method_name;
  275.             $binding['soap:operation']['attr']['soapAction'] = $action;
  276.  
  277.             // INPUT
  278.             $binding['input']['attr'] = '';
  279.             $binding['input']['soap:body']['attr']['use'] = 'encoded';
  280.             $binding['input']['soap:body']['attr']['namespace'] = $method_namespace;
  281.             $binding['input']['soap:body']['attr']['encodingStyle'] = SOAP_SCHEMA_ENCODING;
  282.  
  283.             // OUTPUT
  284.             $binding['output']['attr'] = '';
  285.             $binding['output']['soap:body']['attr']['use'] = 'encoded';
  286.             $binding['output']['soap:body']['attr']['namespace'] = $method_namespace;
  287.             $binding['output']['soap:body']['attr']['encodingStyle'] = SOAP_SCHEMA_ENCODING;
  288.         }
  289.     }
  290.  
  291.     function _generate_DISCO_XML($disco_array)
  292.     {
  293.         $disco = '<?xml version="1.0"?>';
  294.         foreach ($disco_array as $key => $val) {
  295.             $disco .= $this->_arrayToNode($key,$val);
  296.         }
  297.         $this->disco = $disco;
  298.     }
  299.  
  300.     function _generate_WSDL_XML()
  301.     {
  302.         $wsdl = '<?xml version="1.0"?>';
  303.         foreach ($this->_wsdl as $key => $val) {
  304.             $wsdl .= $this->_arrayToNode($key, $val);
  305.         }
  306.         $this->wsdl = $wsdl;
  307.     }
  308.  
  309.     function _arrayToNode($node_name = '', $array)
  310.     {
  311.         $return = '';
  312.         if (is_array($array)) {
  313.             // we have a node if there's key 'attr'
  314.             if (array_key_exists('attr',$array)) {
  315.                 $return .= "<$node_name";
  316.                 if (is_array($array['attr'])) {
  317.                     foreach ($array['attr'] as $attr_name => $attr_value) {
  318.                         $return .= " $attr_name=\"$attr_value\"";
  319.                     }
  320.                 }
  321.  
  322.                 // unset 'attr' and proceed other childs...
  323.                 unset($array['attr']);
  324.  
  325.                 if (count($array) > 0) {
  326.                     $i = 0;
  327.                     foreach ($array as $child_node_name => $child_node_value) {
  328.                         $return .= $i == 0 ? ">\n" : '';
  329.                         $return .= $this->_arrayToNode($child_node_name,$child_node_value);
  330.                         $i++;
  331.                     }
  332.                     $return .= "</$node_name>\n";
  333.                 } else {
  334.                     $return .= " />\n";
  335.                 }
  336.             } else {
  337.                 // we have no 'attr' key in array - so it's list of nodes with
  338.                 // the same name ...
  339.                 foreach ($array as $child_node_name => $child_node_value) {
  340.                     $return .= $this->_arrayToNode($node_name,$child_node_value);
  341.                 }
  342.             }
  343.         } else {
  344.             // $array is not an array
  345.             if ($array !='') {
  346.                 // and its not empty
  347.                 $return .= "<$node_name>$array</$node_name>\n";
  348.             } else {
  349.                 // and its empty...
  350.                 $return .= "<$node_name />\n";
  351.             }
  352.         }
  353.         return $return;
  354.     }
  355.  
  356.     function _getTypeNs($type)
  357.     {
  358.         preg_match_all("'\{(.*)\}'sm", $type, $m);
  359.         if (isset($m[1][0]) && $m[1][0] != '') {
  360.             if (!array_key_exists($m[1][0],$this->namespaces)) {
  361.                 $ns_pref = 'ns' . count($this->namespaces);
  362.                 $this->namespaces[$m[1][0]] = $ns_pref;
  363.                 $this->_wsdl['definitions']['attr']['xmlns:' . $ns_pref] = $m[1][0];
  364.             }
  365.             $typens = $this->namespaces[$m[1][0]];
  366.             $type = ereg_replace($m[0][0],'',$type);
  367.         } else {
  368.             $typens = 'xsd';
  369.         }
  370.         return array($typens,$type);
  371.     }
  372.  
  373.     function _ifComplexTypeExists($typesArray, $type_name)
  374.     {
  375.         if (is_array($typesArray)) {
  376.             foreach ($typesArray as $index => $type_data) {
  377.                 if ($typesArray[$index]['attr']['name'] == $type_name) {
  378.                     return true;
  379.                 }
  380.             }
  381.         }
  382.         return false;
  383.     }
  384. }
  385.